
{ [CNVRT.REC]
[Compile a set of CNVRT rules into a REC program]
[format: ((p)(s)(v) (
	 (pattern, skeleton):	[repeating]
  [or]	 (pattern, skeleton);	[terminal]
	 )) x]
[(p) is a list of pattern definitions ((P1) p1 (P2) p2 ...)]
[(s) is a list of skeleton definitions ((S1) s1 (S2) s2 ...)]
[(v) is a list of variables (v1 v2 ...): digits separated by spaces]
[Patterns may have one of the forms
	all patterns P1,..Pn		(AND,P1,P2,...,Pn)
	first of P1,...Pn to match	(OR,P1,P2,...,Pn)
	pattern does not start w/P	(NOT,P)
	P using P1 as p1 etc		(DEF,P1,p1,...,PN,pn,P)
	Repeat P as much as possible	(ITR,P)
	Repeat P as little as possible	(itr,P)
	... with delimiters /		(QUO/.../)
	the decimal number n		(DEC,n)
	the hexadecimal number n	(HEX,n)
	control character k		(CTL,k)
	lexicographic interval m,n	(IVL,m,n,)
	print remaining workspace	(PWS)
	print value of variable n	(PVR,n)
	wait for keystroke		(HLT)
	print mssg, wait		(HLT,mssg)
	nothing - edit to PWS or HLT	(NOP)
	left angle bracket		(<)
	right angle bracket		(>)
	left parenthesis		<(>
	right parenthesis		<)>
	single quote			<'>
	double quote			<">
	comma				<,>
	balanced parentheses		<()>
	defined pattern a		<:a:>
	interval of length n		<[n]>
	indefinite interval		<-->
	variable n			<n>
	no free space left		<>
	]
[Skeletons may take any one of the following forms
	left parenthesis		<(>
	right parenthesis		<)>
	comma [not necessary]		<,>
	single quote			<'>
	double quote			<">
	left bracket			(<)
	right bracket			(>)
	variable n			<n>
	function f, no argument		(f)
	function f, argument xxx	(f,xxx)
	]
[Since all spaces, tabs, and similar characters are taken literally
  in patterns and skeletons, the pair <<...>> may be used to format
  programs into lines and columns. It is preferable to enclose all
  comments in square brackets at the appropriate place, so that they
  can appear in the compiled program; text between angular brackets,
  on the other hand, will be ignored.]
[Skeletons exploiting CM/M's input-output mechanisms:
	open file			(%O[r|w],D:FILENAME.EXT)
	read file			(%R,D:FILENAME.EXT)
	write file			(%W,D:FILENAME.EXT=xxx)
	close all files			(%E)
	read				(%R)
	type, annul			(%C,xxx)
	type, preserve			(%T,xxx)
	type CR,LF			(%&)
	insert CR,LF			(%|)
	]
[CNVRT is a chain oriented adaptation of the LISP based CONVERT
 described in

	    Adolfo Guzman and Harold V. McIntosh
	    CONVERT
	    Communications of the ACM 9 604-615 (1966).

 The LISP substrate is not a prerequisite for CONVERT, but without
 defining CONVERT as an interpreted language, the exhaustive search
 mechanisms which the full CONVERT requires have to be implemented
 in detail.  For this reason CNVRT employs and and or, rather than
 AND and OR; however the introduction of ITR and itr eliminate much
 of the need for an exhaustive search mechanism; perhaps completely.]
[Harold V. McIntosh, 25 December 1980]
[Harold V. McIntosh, 22 February 1981]
[11 March 1982 - Televideo terminal, REC w/ braces]
[2 July 1983 - (ITR,P) finds maximal iteration of P]
[2 July 1983 - (itr,P) finds minimal iteration of P]
[2 July 1983 - final variable did not check whether defined]
[2 July 1983 - take <, > outside main OR sequence]
[2 July 1983 - begin rule with J, not JZ]
[2 July 1983 - do not log in disk A]
[2 July 1983 - R corrects with echoed backspace]
[3 July 1983 - only terminal NOT preempts remaining space]
[3 July 1983 - long sequences placed in runtime subroutines]
[5 July 1983 - skip rewritten]
[7 July 1983 - systematic use of jJ and zZ]
[7 July 1983 - Y,w,e processes file when space is sufficient]
[20 July 1983 - (OR) never matches]
[30 July 1983 - correction to itr, ITR: note workspace reference]
[30 July 1983 - OR: prefer <:*:> in source to @* in object code]
[30 July 1983 - (NOR,xxx) = (NOT,(OR,xxx))]
[31 July 1983 - OR uses \, AND ` for continuation subroutine]
[24 Nov 1983 - clean up PDL for false E in @>. Gerardo Cisneros]
[24 Nov 1983 - PVR prints the value of a variable.  G.C.]
[24 Nov 1983 - In rule sets using variables, subroutine ";" is generated
		and calls to it are inserted prior to each rule - G.C.]
[25 Nov 1983 - Further PDL cleanup in subroutines "<" and ">". G.C.]
[28 Nov 1983 - default extension CNV for input file. G.C.]
[6 Dec 1983 - PVR code is subroutine "_". Disk I/O included. G.C.]
[8 Dec 1983 - Integer arithmetic (+, -, *) included.  G.C.]
[9 Dec 1983 - Integer division (/) and gcd (|) included. G.C.]
[20 Dec 1983 - P writes WS up to cursor onto disk, 'w' uses P. - HVM]
[22 Dec 1983 - null extension results in automatic compilation - HVM]
[22 Dec 1983 - [non-primitive pattern] <()> for balanced parens - HVM]
[22 Dec 1983 - (PWS,mssg) identifies the typed line with 'mssg' - HVM]
[24 Dec 1983 - a display message at logon can be shown - HVM]
[24 Dec 1983 - initial read, final print of WS is gratuitous - HVM]
[Harold V. McIntosh and Gerardo Cisneros, 28 December 1983]

[30$ - input FCB]
[31$ - output FCB]

[display w/cursor]		(248%I26%TLJZqt248%FD;;) D

[erase cursors]			(J(248%FD:JZ;);) E

[zero file control block]	($m33cmpw0%(f:;)wnnS;) F

[create input, output FCB's]	('5C'H12wA' 'Ew;B
  [generate file name]		 9aQpG'REC'|m (Z3b' 'E'CNV';Q;)|m w
  [open input file]		 n30$rS 30@f
  [open output file]		 n31$rS 31@g31@e
				;) G

[close file]			(
  [clear wkspace, inp file]	 @p:L@y:(@p:0=;e26%(f:;)@p;;)
  [close fil.REC]		 31$r16k
				;) H

[initialize]			(J@Wj@!;@!;) I

[read, with rubout]		(R26%='';T127%(=)(@J|;L@J;);) J

[WS up to cursor to disk]	(jJ<(@p:L;)Zz>;) P

[15-line window]		(AB(10%Fz;Zz;)qL
				  15(d(10%FA;L(26%Fj;Z;)):;)Y<;<) W

[compile one rule]		{
  [insert single quote]	  	(39%I;) q
  [find comma, pass parens]	(zZ<(','E;'<(>'Ez:'<)>'Ez:'<,>'Ez:
				 '(QUO'EzABQzFzA:'('Ez@d:A:)jJ>;J>) r
  [advance to (, <, or end]	('('E;'<'E;','E;A:) h

    [(..., holds pattern]	 ('('F'J'Iz@r<(
    [compile pattern, skeleton]	  @bZ>zZ','FDZ<@dBjJ><j'JZD'I@c ';'I>z')'Fz;)
				 ;) a

[Duplicate and test for null]	(pG''=;L) s
[CNVRT rule set]		('('FD'{'I  
  [defined patterns]		  '('FDZ<@dBDJ><(@hzZ<@dBj';'IjJ<@b>>:;)>
  [defined skeletons]		  '('FDZ<@dBDJ><(@hzZ<@dBj';'IjJ<j@c>>:;)>
  [variable list - save & init]	  '('FzZ<@dBDJ><Qj(A'@( 'Iz' 'ED:;)>
  [variable list - reinitialize]  '('F(@s;D'{('I;)zpG(''=;I<' 'IJj
				(' 'FD'@: 'Iz:;)>;) (@s;';); ('Iz;)
  [one single rule]		  ('('Ej(@s;'@;'Iz;)Z<A@dJ><@aZz>:
					')'ED';)'Iz;A:;)
  [variable list - undefine]	  (@s;'} 'Iz;) pG(''=;I<' 'IJ
					(' 'FD'@) 'Iz:;)>;)
  [variable list - restore]	  ' 'II<j(ABD' nn$S'Iz' 'ED:;)>
				  ')'FD';)}'I 13%Fj
				 ;) } t

[parse pattern]			{
				 (1b39%ED;39%I'Ez'Iz;) E
				 (1b39%ED;39%I'(Fz;Zz<)'Iz;) F
				(z
  [suppress extraneous intvl]	 '<<'E'>>'VD:
  [variable is interval]	 '<['ED @E']>'FD'(a;L)z'I@q :
  [defined pattern]		 '<:'ED @E '@'I':>'FD@q :
  [skip]			 '<-->'ED @E '(('I@qzZ
				    <(@hj;;)>@F 'Z<'Iz
				    @b '>;J>);A:)'I ;
  [left paren]			 '<(>'ED '('I :
  [right paren]			 '<)>'ED ')'I :
  [comma]			 '<,>'ED ','I :
  [balanced parentheses]	 '<()>'ED @E
				   '"("E{(A")"Ez;"("E@*::)*(@*;)}'I
				   @q :
  [single quote]		 10044[<']ED'>'ED@E'39%Ez'I@q :
  [double quote]		 8764[<"] ED'>'ED@E'34%Ez'I@q :
  [physical end]		 '<>'ED @E'(A)'I ;
  [variable follows]		 '<'ED @E
				    '>'UQD'>'ED Z<((@hjJ>Qj)J>Qj
				    ''=I'@]'I;
				    ' {[vbl] ('Iz @b ';) = ('I
				    (''=I'@<'I;@qI@qI'@>'I;)
				    ';)}[vbl] 'I ;) ;
  [DEF follows]			 '(DEF,'ED @E
				    zZ<@dBDJQD>' {[def] ('Iz
				    (I<j@rzABDZQDJ<@b>';) 'I>
					I<j@rzABDZQDJ>' ('I:
				        <@b>';)}[def] 'Iz>;)@q :
  [ITR follows]			 '(ITR,'ED @E '([ITR] Z<'I
				    zZ<@dBDJ><@b>'>:J>;)[ITR] 'I@q :
  [itr follows]			 '(itr,'ED @E
				    zZ<@dBDJQD>' ([itr] Z<'IzZ <@b>
				    '>; J>'II <@b> ':) [itr] 'I ;
  [AND follows]			 '(AND,'ED @E
				    zZ<@dBDZQDJj@rz','EDZQDJj
				    ' {[AND] ('IzZ<j';) ` (Z<'Iz
				    Z<@b>'@`>;>)}[AND] 'I
				    (Jj>' {('IzZ<j';) ` (jJ><'II
				    <(j@rz','EDZQD;)
				    J<@b>'(A)@`;)} 'I>:
				    J<@b>'(A)@`;)} 'I>;)
				    Jj'>('II<@b>'<;<)'I>>Zz ;
  [OR follows]			 '(OR)'ED @E '()'I@q:
				 '(OR,'ED @E  zZ<@dBDJQD>
				    ' {[OR] ('IzZ <@b> ';) \ (Z<('I
				    (I<j@rzABD'<:\:>'IzZQDJ<@b>'; J'I>:
				    <'<:\:>'IJ@b>';)>;>)} [OR] 'Iz>;) ;
  [and follows]			 '(and)'ED @E @q:
				 '(and,'ED @E  zZ<@dBDJQD>
				    ' [and] Z<('I
				    I<j@rzABDZQDJ<@b>' jJ><'I>
				    (I<j@rzABDZQDJ<@b>' (A)J><'I>:
				    <@b>'(A);>)> [and] 'Iz>;) @q:
  [or follows]			 '(or)'ED @E '()'I@q:
				 '(or,'ED @E  zZ<@dBDJQD>
				    ' [or] Z<('I
				    (I<j@rzABDZQDJ<@b>'; J'I>:
				    <@b>';>)> [or] 'Iz>;) @q:
  [NOT follows]			 '(NOT,'ED @E'[not] (Z< 'I
				    zZ<@dBDJ><@b>
				    'J>)J>[not] 'I(zABj;'Zz'I;)@q :
  [nor follows]			 '(nor,'ED Z<j'(NOT,(or,'Iz@d')'IJj> :
  [QUO follows]			 '(QUO'ED @E zABQD@qFD')'ED@E@q :
  [DEC follows]			 '(DEC,'ED @E ')'FD'%Ez'I@q :
  [HEX follows]			 '(HEX,'ED @E ')'UQD')'EDHI'%Ez'I@q :
  [CTL follows]			 '(CTL)'ED @E'0%31%Mz'I@q :
				 '(CTL,'ED @E ')'UQD')'ED
				    I<j(ABQD\64['@']-#'%Ez'|Iz:;)>@q :
  [IVL follows]			 '(IVL'ED @E ABQQD@qFD@q
				    @qFD')'ED@q'Mz'I@q :
  [PWS follows]			 '(PWS)'ED @E'2573TLZqtj'I@q :
				 '(PWS,'ED @E'2573TL'I@q')'FD@q'TLZqtj'I@q :
  [HLT follows]			 '(HLT)'ED @E'RL'I@q :
				 '(HLT,'ED @E'2573TL'I@q')'FD@q'TLRL'I@q :
  [NOP follows]			 '(NOP)'ED :
				 '(NOP,'E ')'VD :
  [PVR follows]			 '(PVR,'ED @E ')'FD"'_'@%"I@q:
  [left angle bracket]		 '(<)'ED '<'I :
  [right angle bracket]		 '(>)'ED '>'I :
				 A:@E;) B (j@q@Bz;)} b

[parse skeleton]		{(1b39%ED;39%I'I'I;) Q
				 (z@q3bjA@qZQ|D:DJj'@'IZQ|D'Z>'|I>;) h
				 (z
				  '<<'E'>>'VD:
				  '<(>'ED'('I:
				  '<)>'ED')'I:
				  '<,>'ED','I:
				  10044[<']ED'>'ED@Q'39%I'I@q:
				   8764[<"]ED'>'ED@Q'34%I'I@q:
				  '<'ED@Q'>'FD'@['I@q:
				  '(<)'ED'<'I:
				  '(>)'ED'>'I:
				  '('ED@Qz')'V
				     (<j','UQD','ED>'z<'I@cI<''@h;
				     j'z<'Iz')'U<''@h')'FD>;)@q:
				  ')'ED;
				  A:;) C (@q@C@Q;)} c

[rparen, pass pairs, (QUO's]	(')'Ez;'<(>'Ez:'<)>'Ez:
				 '(QUO'EzABQzFzA:'('Ez@d:A:)d
[open file or create it]	(@h$r15K(255=22K;;)LL;)e
[open file or report absence]	(@h$r15K(255='new file 'T;;)LL;)f
[delete file if present]	(@h$r19k;)g
[CP/M's DMA address]		('80'H26k;)h
[write one record]		(@Ej26%EZD0;128aqL26k31$r21kD'.'TL;) p

[CNVRT subroutines]		("{
   				{
    [find/make FCB]		(Jj'TTY:'EQZD;(':'UQD':'ED\64-%;0%;)
				 ('.'U<(8a;@b;)Q|D>;Z'.DAT'IJj:)
				  '.'FJDZ(3a;@b;)Q|JZDI
				 32(dpGm$r0=npGpGd0&$Sm@znpGQ&$rrS0;
				 r12wQmwnEn;n:)D;) f
    [blank fill by count]	(Zz(d' 'I:;)JZ;) b
    [zero fill]			(cmpw0%(f:;)w;) 0
    [zero FCB & buffer]		($m33@0130@0nn&0||pLnS;) z
    [set default input file]	(0,30$S'5C'H12wA' 'Ew4@0n0|0|pL31$S
				 'TTY:'31$rrS; B9aQD(3a'   'E
				 'DAT';Q;)|mw31@zn31$rrS31@r;) i
    [open for read]		(@hr15K(255='NO FILE'I;L;)L;) r
    [open for write]		(@hpGpG4+1&SrpG19k22k^^r128&S;) w
    [set DMA address]		($rpG^^r^^26k;) h
    [open]			(m@f0=n@@;nLL;) O
    [read]			(''(AL@f(0=pG@r;'TTY:'(='T');))
				 ('T'='';L31pG$rr12w'TTY:'Ew;w)
				 L@&'> 'TL(@#I;:);
				 $r(pG^^rpGmr(0=(npGpGm128&S^^26kpGr
				 20K0=L;LL1npGpGm129+26%&SS;)npGmr;;)
				 pG130&-n+&dm(u13%=;10%(=)pGI(26%=;
				 L);ndm:)L^^rn&S;LpG^^r0&S:);) R
    [write]			(Jj'='U<(A@f'TTY:'(=)(0=pG@w;;))>'='ED
				 ZqtD; >'='EDZ<@g;) W
    [write to disk]		($r(pG^^rpGpGmrpGm- 130+n&maQD>Z<nSn^^
				 26kpGr21kpG^^r128&S:JZQD>nSnSL;);) g
    [close all files]		(31pGm($r0=;pG4+r(0=L;LJj26%I<npGm@gpG
				 ^^rpGr127(N^^26kpGr21k;L;)r16k;)ndpGm:)
				 nL;;) E
    [PVR]			(pG@&#'= '|TL$r(0='undef';yG;)TL;) _
    [cr, lf]			(2573TL;)&
    [insert cr, lf]		(2573I;)|
    [read console]		(R13%='';08%(=)(T@#|;08%T' 'TLTLL@#;);)#
    [type comment]		(@TD;)C
    [display at logon]		('[[]]'TL@&;)D
    [write workspace]		(@&JZqt;)T
				(@@;) }%
    [integer arithmetic]	{(+;)+ (-;)- (*;)* (/&L;)/
				(pGm/L1=nL1;0=n;n&:)|
				 ((pGmJj(U);QD(O)I;npGmEDZQD(O)IjnpGmI;
				 n@@#I)nLJZ;;) } #
    [save & init variables]	(pGpGm$rm0&$S;) (
    [reinitialize variable]	(pG$r0=L;LnL0&$S;) :
    [undefine variable]		($r0=;LnL;) )
    [compare/define variable]	(pG$r0=ZQzml&$S;&LyGEz;) ]
    [body of variable search]	(pG$r(0=)yG(E;&L)z&L@=L;pG$r(0=;LL)
				  Z<((&pGm&n(F;''mZz<)jJQmpGl&$S
				  zZ<@=>;J>);nLA:0&$SL>)>LL;) >
    [body of variable search]	(pG$r(0=)yGEz@=L;pG$r(0=;LL)
				  Z<((jJQmpGl&$S
				  zZ<@=>;J>);nLA:0&$S>)>L;) <
    [insert variable]		($ryGI;) [
				"I;) s

[CNVRT postscript]		(' ~'I2573I
				  "('i'@%'D'@%'R'@%@~JZqt'c'@%;)  }"I
				;) u

[compile a CNVRT file]		(
  [read max 1K from disk]	  8(d(@y;;):;) J
  [change file extension]	  ('.CNV]'FD'.REC]'Iz;;)
  [find display message]	  ('[['F']]'UQD;'cnvrt/icuap/1983';)
  [look for code gap]		  ('('Ej;2573Ez2573Ez2573Ez2573Ej2bD;A:;)
  [insert preface; to disk]	  's'TL@s<'[[]]'FDIZ>z@P
  [load rest of file]		  Z<(@y:;)Jj>
  [compile each function]	  ('t'TL@t@P'('Fj:;)
  [insert postscript]		  'u'TL@u@P
  [close file]		  	  @H
				;) w

[append a record]		(128(e)L;qL26k30$r20K0=L;DLL@h) y
[back to line feed]		(10%Ez;B:j;) 0
[bracket a line]		(@010%V;Z;) 1
[back to preceding line]	(@0BB@0;;) 2
[cr,lf]				(2573TL;) &
[read w/error correction]	(RT95%=127%;13%=2573;26%(=);) $
[clear screen]			(26%TL;) !
[erase on ro, insert others]	(127%=z(B;;)D;I;) :
[form next window]		(Zz>@W@!;) >
[cancel line]			(24%TL;) ^

(	'd' [delete] =		(ABD;;);
	'i' [insert] =		(@D@$@::;)@!;
	'j' [beginning] =	Jj;
	'x' [exchange] =	(ABD;;)RTI;
	'z' [to end] =		Z;
	127%[delete] =		@1D@!;
	10% [down arrow] =	(10%FA;J>(10%FA;;)@Wz@!;;)@!;
	13% [carr ret] =	@0;
	11% [up arrow] =	(BA@2;J>@2@Wj@!;;);
	08% [left arrow] =	(Bj;;);
	'n' [next record] =	>(@p;L;)(@y;;)J(@W;;);
	'p' [write 1 record] =	>(@p;L;)J(@W;;);
	'P' [dump to cursor] =	>@P248%I@2(@W;;)J248%FD;
	'y' [read 1 record] =	>(@y;'eof:'TL;)J(@W;;);
	'Y' [read file] =	>(@y:;)J(@W;;)Jj;
	' ' [advance] =		(A;;);
	'>' [next window] =	(@>j;>@I;);
	'<' [beg window] =	>@I;
	',' [end of line] =	(2573Fj;Zz;)@!;
	'.' [refresh screen] =	@!;
	's'			= @s;
	't'			= >@t@!(@W;;)Jj;
	'u'			= @u;
	'w'			= >@wJ<(26%Fj;Z;)J><;
	) ?

[main program]			(
    [create FCB's, open files]	 30@F 31@F @G
    [sign-on message]		 'cnvrt.rec> 'TL
    [automatic compilation]	 ('5C'H12wAqt@&3b' 'Ew@w;w);
    [wait, initialize, loop]	 RTL @I (@DR
	[exit at once]		     ';'=;
	[close, exit]		     'e'=>@H;
	[read menu]		     @?:
	[ignore unknown]	     L:);)}

[end]
